package com.wanji.gateway.config;

import com.wanji.gateway.constant.MessageType;
import com.wanji.gateway.event.DeviceMessageEvent;
import com.wanji.gateway.processor.AlertDataProcessor;
import com.wanji.gateway.processor.SensorDataProcessor;
import com.wanji.gateway.processor.StatusDataProcessor;
import com.wanji.protocol.api.DeviceMessage;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.MessageChannels;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;

import java.util.concurrent.ExecutorService;

@Configuration
@EnableIntegration
@RequiredArgsConstructor
public class IntegrationConfig {

    private final SensorDataProcessor sensorProcessor;
    private final StatusDataProcessor statusProcessor;
    private final AlertDataProcessor alertProcessor;
    private final ExecutorService executorService;

    @Bean
    @Qualifier("deviceInputChannel")
    public MessageChannel deviceInputChannel() {
        return new DirectChannel();
    }


    @Bean
    public ApplicationListener<DeviceMessageEvent> eventListener(@Qualifier("deviceInputChannel") MessageChannel deviceInputChannel) {
        return event -> {
            Message<DeviceMessage> message = MessageBuilder.withPayload(event.getMessage()).setHeader("DEVICE_ID", event.getDeviceId()).build();
            deviceInputChannel.send(message);
        };
    }

    @Bean
    public IntegrationFlow processingFlow() {
        return IntegrationFlow.from("deviceInputChannel")
                .channel(MessageChannels.executor(executorService))
                .route(DeviceMessage.class,
                        DeviceMessage::getType,
                        mapping -> mapping
                                .subFlowMapping(MessageType.SENSOR_DATA.name(),
                                        sf -> sf.handle(sensorProcessor, "process"))
                                .subFlowMapping(MessageType.STATUS_UPDATE.name(),
                                        sf -> sf.handle(statusProcessor, "process"))
                                .subFlowMapping(MessageType.ALERT.name(),
                                        sf -> sf.handle(alertProcessor, "process"))
                                // 默认处理,发送到父流程默认处理器
                                .defaultOutputToParentFlow()
                                // 忽略发送失败
                                .ignoreSendFailures(true)
                                // 允许无匹配路由
                                .resolutionRequired(false))
                // 父流中的默认处理
                .handle(sensorProcessor, "process")
                .get();
    }
}